﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.Utility
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using Microsoft.Win32.SafeHandles;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IdentityModel.Tokens;
using System.IO;
using System.Net;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Principal;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Text;
using System.Threading;
using System.Xml;

namespace Microsoft.InfoCards
{
  internal static class Utility
  {
    public static WindowsIdentity GetWindowsIdentity(IntPtr rpcBindingHandle)
    {
      InfoCardTrace.ThrowInvalidArgumentConditional(IntPtr.Zero == rpcBindingHandle, nameof (rpcBindingHandle));
      uint num = NativeMethods.RpcImpersonateClient(rpcBindingHandle);
      if (num != 0U)
        throw InfoCardTrace.ThrowHelperError((Exception) new CommunicationException(SR.GetString("ServiceInvalidCallerToken"), (Exception) new Win32Exception((int) num)));
      try
      {
        return WindowsIdentity.GetCurrent(true);
      }
      finally
      {
        InfoCardTrace.Assert(0U == NativeMethods.RpcRevertToSelfEx(rpcBindingHandle), "rpcIdentity");
      }
    }

    public static uint GetRpcClientPid(IntPtr rpcBindingHandle)
    {
      uint pid;
      uint num = NativeMethods.I_RpcBindingInqLocalClientPID(rpcBindingHandle, out pid);
      if (num != 0U)
        throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception((int) num));
      return pid;
    }

    public static void ClearUnsafeMemory(IntPtr ptr, int count)
    {
      NativeMethods.ZeroMemory(ptr, count);
    }

    public static void ThrowIfProcessExited(SafeWaitHandle processHandle)
    {
      using (AutoResetEvent autoResetEvent = new AutoResetEvent(false))
      {
        autoResetEvent.SafeWaitHandle = processHandle;
        if (autoResetEvent.WaitOne(0, false))
          throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("ServiceProcessHasExited")));
      }
    }

    public static void SerializeString(BinaryWriter writer, string str)
    {
      int num = 0;
      if (string.IsNullOrEmpty(str))
      {
        writer.Write(num);
      }
      else
      {
        writer.Write(str.Length);
        writer.Write(str.ToCharArray());
      }
    }

    public static void SerializeUri(BinaryWriter writer, Uri uri)
    {
      if ((Uri) null == uri)
        Utility.SerializeString(writer, (string) null);
      else
        Utility.SerializeString(writer, uri.ToString());
    }

    public static void SerializeBytes(BinaryWriter writer, byte[] bytes)
    {
      int count = 0;
      if (bytes != null)
        count = bytes.Length;
      Utility.SerializeBytes(writer, bytes, 0, count);
    }

    public static void SerializeBytes(
      BinaryWriter writer,
      byte[] bytes,
      int startOffset,
      int count)
    {
      int num = 0;
      if (bytes == null)
      {
        writer.Write(num);
      }
      else
      {
        writer.Write(count);
        writer.Write(bytes, startOffset, count);
      }
    }

    public static string DeserializeString(BinaryReader reader)
    {
      return new string(reader.ReadChars(reader.ReadInt32()));
    }

    public static Uri DeserializeUri(BinaryReader reader)
    {
      return new Uri(Utility.DeserializeString(reader));
    }

    public static bool CompareUri(string first, string second)
    {
      try
      {
        return Utility.CompareUri(new Uri(first), new Uri(second));
      }
      catch (UriFormatException ex)
      {
        throw InfoCardTrace.ThrowHelperError((Exception) new InfoCardArgumentException(SR.GetString("InvalidUriFormat"), (Exception) ex));
      }
    }

    public static bool CompareUri(Uri first, Uri second)
    {
      return first == second;
    }

    public static bool ArrayIsNullOrEmpty(Array inArray)
    {
      return inArray == null || inArray.Length == 0;
    }

    public static SafeWaitHandle GetLocalHandleFromRemoteHandle(
      SafeWaitHandle hRemote,
      int remotePid)
    {
      SafeWaitHandle targetHandle;
      using (new SystemIdentity(false))
      {
        using (SafeNativeHandle sourceProcessHandle = NativeMethods.OpenProcess(64, false, remotePid))
        {
          if (sourceProcessHandle == null || sourceProcessHandle.IsInvalid)
            throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error()));
          if (!NativeMethods.DuplicateHandle(sourceProcessHandle, hRemote, new SafeNativeHandle(NativeMethods.GetCurrentProcess(), false), out targetHandle, 2, false, 0))
          {
            int lastWin32Error = Marshal.GetLastWin32Error();
            InfoCardTrace.CloseInvalidOutSafeHandle((SafeHandle) targetHandle);
            throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(lastWin32Error));
          }
        }
      }
      return targetHandle;
    }

    public static SafeWaitHandle GetRemoteHandleFromLocalHandle(
      SafeWaitHandle hLocal,
      Process remoteProcess)
    {
      SafeWaitHandle targetHandle = (SafeWaitHandle) null;
      using (new SystemIdentity(false))
      {
        try
        {
          if (!NativeMethods.DuplicateHandle(new SafeNativeHandle(NativeMethods.GetCurrentProcess(), false), hLocal, new SafeNativeHandle(remoteProcess.Handle, false), out targetHandle, 1048578, false, 0))
            throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error()));
          bool success = false;
          targetHandle.DangerousAddRef(ref success);
        }
        catch (Exception ex)
        {
          if (InfoCardTrace.IsFatal(ex))
            throw;
        }
      }
      return targetHandle;
    }

    public static SafeJobHandle CreateJobObjectWithSdHelper(string trustedUserSid)
    {
      SafeJobHandle safeJobHandle = new SafeJobHandle();
      RuntimeHelpers.PrepareConstrainedRegions();
      try
      {
      }
      finally
      {
        IntPtr zero = IntPtr.Zero;
        uint jobObjectWithSd = NativeMcppMethods.CreateJobObjectWithSD(ref zero, trustedUserSid);
        if (jobObjectWithSd != 0U)
          throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception((int) jobObjectWithSd));
        safeJobHandle.UpdateHandle(zero);
      }
      return safeJobHandle;
    }

    public static IntPtr ReadHandle(BinaryReader br)
    {
      IntPtr zero = IntPtr.Zero;
      return 4 != IntPtr.Size ? (IntPtr) br.ReadInt64() : (IntPtr) br.ReadInt32();
    }

    public static byte[] CreateHash(byte[] firstArray, Uri cardId)
    {
      using (SHA256 shA256 = (SHA256) new SHA256Managed())
      {
        byte[] hash = shA256.ComputeHash(Encoding.Unicode.GetBytes(cardId.ToString()));
        byte[] buffer = new byte[firstArray.Length + hash.Length];
        Array.Copy((Array) firstArray, 0, (Array) buffer, 0, firstArray.Length);
        Array.Copy((Array) hash, 0, (Array) buffer, firstArray.Length, hash.Length);
        return shA256.ComputeHash(buffer);
      }
    }

    public static byte[] CreateHash(byte[] firstArray, byte[] secondArray, byte[] thirdArray)
    {
      byte[] buffer = new byte[firstArray.Length + secondArray.Length + thirdArray.Length];
      Array.Copy((Array) firstArray, 0, (Array) buffer, 0, firstArray.Length);
      Array.Copy((Array) secondArray, 0, (Array) buffer, firstArray.Length, secondArray.Length);
      Array.Copy((Array) thirdArray, 0, (Array) buffer, firstArray.Length + secondArray.Length, thirdArray.Length);
      using (SHA256 shA256 = SHA256.Create())
        return shA256.ComputeHash(buffer);
    }

    public static bool CompareByteArrays(byte[] arr1, byte[] arr2)
    {
      bool flag = true;
      if (arr1 == null && arr2 == null)
        return true;
      if (arr1 == null || arr2 == null || arr1.Length != arr2.Length)
        return false;
      for (int index = 0; index < arr2.Length; ++index)
      {
        if ((int) arr1[index] != (int) arr2[index])
        {
          flag = false;
          break;
        }
      }
      return flag;
    }

    public static string ResolvePPID(
      string input,
      byte[] issuerIdentiferAsBytes,
      StoreConnection connection)
    {
      string empty = string.Empty;
      byte[] arr2 = Convert.FromBase64String(input);
      ICollection collection = (ICollection) connection.Query(QueryDetails.FullRow, new List<QueryParameter>()
      {
        new QueryParameter("ix_objecttype", new object[1]
        {
          (object) 1
        }),
        new QueryParameter("ix_production_svc_uri", new object[1]
        {
          (object) "http://schemas.xmlsoap.org/ws/2005/05/identity/issuer/self"
        })
      }.ToArray());
      if (collection != null && collection.Count > 0)
      {
        foreach (DataRow dataRow in (IEnumerable) collection)
        {
          byte[] dataField = dataRow.GetDataField();
          try
          {
            using (MemoryStream memoryStream = new MemoryStream(dataField))
            {
              InfoCard infoCard = new InfoCard((Stream) memoryStream);
              if (Utility.CompareByteArrays(Utility.CreateHash(issuerIdentiferAsBytes, infoCard.Id), arr2))
              {
                empty = infoCard.Id.ToString();
                break;
              }
            }
          }
          finally
          {
            Array.Clear((Array) dataField, 0, dataField.Length);
          }
        }
      }
      return empty;
    }

    public static bool GetCertHAFlags(
      X509Certificate2 certificate,
      X509Certificate2Collection supportingCertificates,
      ref Utility.SubjectAtrributeHAFlags certFlags)
    {
      int haFlags = 0;
      X509Chain chain;
      try
      {
        InfoCardX509Validator.ValidateChain(certificate, supportingCertificates, out chain);
      }
      catch (SecurityTokenValidationException ex)
      {
        InfoCardTrace.TraceAndLogException((Exception) ex);
        return false;
      }
      InfoCardTrace.Assert(null != chain, "Should have been populated by ValidateChain");
      bool highAssuranceFlags = NativeMcppMethods.GetHighAssuranceFlags(chain.ChainContext, ref haFlags);
      certFlags = (Utility.SubjectAtrributeHAFlags) haFlags;
      if (highAssuranceFlags && !Utility.IsSubjectAtrributeHAFlagsSet(certFlags, Utility.SubjectAtrributeHAFlags.Enabled))
        throw InfoCardTrace.ThrowHelperError((Exception) new UntrustedRecipientException(SR.GetString("InvalidHACertificateStructure")));
      return highAssuranceFlags;
    }

    public static bool IsSubjectAtrributeHAFlagsSet(
      Utility.SubjectAtrributeHAFlags currentValue,
      Utility.SubjectAtrributeHAFlags testFlag)
    {
      return (testFlag & currentValue) == testFlag;
    }

    public static int CalculateIncreaseByPercent(
      int oldSize,
      int alignToByteBoundary,
      int percentIncrease)
    {
      uint uint32 = Convert.ToUInt32(alignToByteBoundary);
      uint num = Convert.ToUInt32((1.0 + (double) percentIncrease / 100.0) * (double) oldSize);
      if (num == 0U)
        num = uint32;
      else if (num % uint32 > 0U)
        num += uint32 - num % uint32;
      return Convert.ToInt32(num);
    }

    public static string CreatePpid(byte[] certIdentifierAsBytes, Uri cardId)
    {
      return Convert.ToBase64String(Utility.CreateHash(certIdentifierAsBytes, cardId));
    }

    public static EndpointAddress DeriveMexAddress(EndpointAddress epr)
    {
      EndpointAddress endpointAddress = (EndpointAddress) null;
      try
      {
        if ((XmlReader) epr.GetReaderAtMetadata() != null)
        {
          foreach (MetadataSection metadataSection in MetadataSet.ReadFrom((XmlReader) epr.GetReaderAtMetadata()).MetadataSections)
          {
            if (metadataSection.Metadata is MetadataReference && (EndpointAddress) null != ((MetadataReference) metadataSection.Metadata).Address && string.Compare(((MetadataReference) metadataSection.Metadata).Address.Uri.Scheme, "https", StringComparison.OrdinalIgnoreCase) == 0)
            {
              endpointAddress = ((MetadataReference) metadataSection.Metadata).Address;
              break;
            }
          }
        }
      }
      catch (Exception ex)
      {
        if (InfoCardTrace.IsFatal(ex))
          throw;
      }
      return endpointAddress;
    }

    public static XmlDictionaryReader CreateReaderWithQuotas(string root)
    {
      byte[] bytes = new UTF8Encoding().GetBytes(root);
      return XmlDictionaryReader.CreateTextReader(bytes, 0, bytes.GetLength(0), (Encoding) null, InfoCardConstants.DefaultQuotas, (OnXmlDictionaryReaderClose) null);
    }

    public static XmlDictionaryReader CreateReaderWithQuotas(Stream input)
    {
      return XmlDictionaryReader.CreateTextReader(input, (Encoding) null, InfoCardConstants.DefaultQuotas, (OnXmlDictionaryReaderClose) null);
    }

    public static MemoryStream ReadByteStreamFromBase64(XmlReader reader)
    {
      MemoryStream memoryStream = new MemoryStream();
      if (!reader.IsEmptyElement && reader.Read() && reader.NodeType != XmlNodeType.EndElement)
      {
        byte[] buffer = new byte[1024];
        int count;
        while ((count = reader.ReadContentAsBase64(buffer, 0, buffer.Length)) > 0)
          memoryStream.Write(buffer, 0, count);
        memoryStream.Flush();
        memoryStream.Seek(0L, SeekOrigin.Begin);
      }
      return memoryStream;
    }

    public static BindingElementCollection UpdateProxyForHttpAndRestrictTransportBinding(
      BindingElementCollection source,
      IWebProxy proxy,
      bool turnOffClientAuthOnTransport)
    {
      InfoCardTrace.Assert(null != source, "Do not expect a null bindingElementCollection");
      if (source.Find<TransportBindingElement>() == null)
        throw InfoCardTrace.ThrowHelperError((Exception) new UnsupportedPolicyOptionsException());
      BindingElementCollection elementCollection = HttpProxyTransportBindingElement.ReplaceHttpTransportWithProxy(source, proxy, turnOffClientAuthOnTransport);
      TransportBindingElement transportBindingElement = elementCollection.Find<TransportBindingElement>();
      InfoCardTrace.Assert(null != transportBindingElement, "We ensured there is a TransportBindingElement at the start of this function");
      transportBindingElement.MaxReceivedMessageSize = (long) InfoCardConstants.MaximumMessageSize;
      if (!(transportBindingElement is TcpTransportBindingElement) && !(transportBindingElement is HttpProxyTransportBindingElement))
      {
        InfoCardTrace.Assert(null == transportBindingElement as HttpTransportBindingElement, "Http(s)TransportBindingElement should have been replaced by HttpProxyTransportBindingElement above");
        throw InfoCardTrace.ThrowHelperError((Exception) new UnsupportedPolicyOptionsException());
      }
      if (turnOffClientAuthOnTransport)
      {
        Collection<StreamUpgradeBindingElement> all = elementCollection.FindAll<StreamUpgradeBindingElement>();
        InfoCardTrace.Assert(all != null && 1 >= all.Count, "Should not be null (even if empty) and there should be at most one StreamUpgradeBindingElement");
        foreach (StreamUpgradeBindingElement upgradeBindingElement in all)
        {
          if (!(upgradeBindingElement is SslStreamSecurityBindingElement))
            throw InfoCardTrace.ThrowHelperError((Exception) new UnsupportedPolicyOptionsException());
        }
      }
      return elementCollection;
    }

    public static bool KillHelper(Process p)
    {
      bool flag = false;
      if (!p.HasExited)
      {
        try
        {
          p.Kill();
          flag = true;
        }
        catch (InvalidOperationException ex)
        {
        }
        catch (Win32Exception ex)
        {
          if (5 != ex.NativeErrorCode)
            throw ex;
        }
      }
      return flag;
    }

    [System.Flags]
    public enum SubjectAtrributeHAFlags
    {
      NotEnabled = 0,
      Enabled = 1,
      OrganizationHA = 2,
      LocStateCountryHA = 4,
      LogoHA = 8,
    }
  }
}
